﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace IndustryWrapper
{
    /// <summary>
    /// XML序列化管理器
    /// </summary>
    public class CXmlSerializerManager
    {
        //系统自带的无法实现list的序列化
        //使用第三方的来做
        #region list序列化
        /// <summary>
        /// 把一个list序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serialObject"></param>
        /// <returns></returns>

        public static string XmlSerializerFromList<T>(T serialObject) where T : class

        {

            var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });

            var serializer = new XmlSerializer(serialObject.GetType());

            var settings = new XmlWriterSettings();

            settings.OmitXmlDeclaration = true;

            settings.Encoding = Encoding.UTF8;

            using (var stream = new StringWriter())

            using (var writer = XmlWriter.Create(stream, settings))

            {

                serializer.Serialize(writer, serialObject, emptyNamepsaces);

                return stream.ToString();

            }

        }

        /// <summary>

        ///反序列化

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <param name="xml"></param>

        /// <returns></returns>

        public static T DeserializeObjectToList<T>(string xml) where T : class

        {

            using (var str = new StringReader(xml))

            {

                var xmlSerializer = new XmlSerializer(typeof(T));

                var result = (T)xmlSerializer.Deserialize(str);

                return result;

            }

        }
        #endregion
        #region 系统自带的序列化
        /// <summary>
        /// serialize object to xml file.
        /// </summary>
        /// <param name="path">the path to save the xml file</param>
        /// <param name="obj">the object you want to serialize</param>
        public static bool save(object obj, string path)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(obj.GetType());
                string content = string.Empty;
                //serialize
                using (StringWriter writer = new StringWriter())
                {
                    serializer.Serialize(writer, obj);
                    content = writer.ToString();
                }
                //save to file
                using (StreamWriter stream_writer = new StreamWriter(path))
                {
                    stream_writer.Write(content);
                }
                return true;
            }
            catch (Exception e)
            {
                string msg = e.Message;
                return false;
            }

        }

        /// <summary>
        /// deserialize xml file to object
        /// </summary>
        /// <param name="path">the path of the xml file</param>
        /// <param name="object_type">the object type you want to deserialize</param>
        public static object read(string path, Type object_type)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(object_type);
                using (StreamReader reader = new StreamReader(path))
                {
                    return serializer.Deserialize(reader);
                }
            }
            catch (Exception)
            {
                //System.Windows.Forms.MessageBox.Show("文件:" + path + "读取失败!");
                return null;
            }
        }
        #endregion
    }

    /// <summary>
    /// xml序列化
    /// 这个类使用的是系统自带的反射来保存所有的共有成员
    /// 内部不允许有其他的共有接口之类的
    /// 否则会报错
    /// </summary>
    public class CXmlSaveRead
    {
        /// <summary>
        /// serialize object to xml file.
        /// </summary>
        /// <param name="path">the path to save the xml file</param>
        /// <param name="obj">the object you want to serialize</param>
        public static bool save(object obj,string path)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(obj.GetType());
                string content = string.Empty;
                //serialize
                using (StringWriter writer = new StringWriter())
                {
                    serializer.Serialize(writer, obj);
                    content = writer.ToString();
                }
                //save to file
                using (StreamWriter stream_writer = new StreamWriter(path))
                {
                    stream_writer.Write(content);
                }
                return true;
            }
            catch (Exception e)
            {
                string msg = e.Message;
                return false;
            }
            
        }

        /// <summary>
        /// deserialize xml file to object
        /// </summary>
        /// <param name="path">the path of the xml file</param>
        /// <param name="object_type">the object type you want to deserialize</param>
        public static object read(string path, Type object_type)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(object_type);
                using (StreamReader reader = new StreamReader(path))
                {
                    return serializer.Deserialize(reader);
                }
            }
            catch (Exception)
            {
                //System.Windows.Forms.MessageBox.Show("文件:" + path + "读取失败!");
                return null;
            }
        }
    }
    /// <summary>
    /// 读写xml参数
    /// 这个类只适合于一个类中只有一层的情况
    /// 公有变量都会保存成xml
    /// </summary>
    public class ParameterReadSaver
    {
        /// <summary>
        /// 传递一个对象进来,会把里面的所有公有变量保存成XML
        /// </summary>
        /// <param name="obj"></param>
        public static bool save(object obj, string xml)
        {
            Type t = obj.GetType();
            try
            {
                //文档
                System.Xml.XmlWriterSettings set = new System.Xml.XmlWriterSettings();
                set.Indent = true;
                set.NewLineOnAttributes = false;
                System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(xml, set);
                writer.WriteStartDocument();
                writer.WriteStartElement("Parameter");

                writer.WriteStartElement(t.Name);
                System.Reflection.MemberInfo[] minfos = t.GetMembers();
                foreach (System.Reflection.MemberInfo minfo in minfos)
                {
                    System.Reflection.FieldInfo fi = obj.GetType().GetField(minfo.Name);
                    if (fi != null)//获取公有变量
                    {
                        writer.WriteElementString(minfo.Name, fi.GetValue(obj).ToString());
                    }
                }
                writer.WriteEndElement();

                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Flush();
                writer.Close();
                return true;
            }
            catch (Exception)
            {
                System.Windows.Forms.MessageBox.Show("保存参数失败:" + t.Name);
                return false;
            }
        }
        /// <summary>
        /// 指定XML文档,对对象中所有的公有变量赋值
        /// 只有内部指定了的参数会被保存
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="xml"></param>
        public static bool read(object obj, string xml)
        {
            Type t = obj.GetType();
            try
            {
                //解析XML文件
                System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                doc.Load(xml);
                if (doc != null)
                {
                    System.Xml.XmlElement root = doc.DocumentElement;
                    if (root != null && root.Name == "Parameter")
                    {
                        System.Reflection.MemberInfo[] minfos = t.GetMembers();
                        foreach (System.Reflection.MemberInfo minfo in minfos)
                        {
                            System.Reflection.FieldInfo fi = obj.GetType().GetField(minfo.Name);
                            if (fi != null)
                            {
                                System.Xml.XmlNode node = root.SelectSingleNode("/Parameter/" + t.Name + "/" + minfo.Name);
                                if (node != null)
                                {
                                    if (fi.GetValue(obj) is int)
                                    {
                                        int tmpValue = int.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is float)
                                    {
                                        float tmpValue = float.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is double)
                                    {
                                        double tmpValue = double.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is bool)
                                    {
                                        bool tmpValue = bool.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is short)
                                    {
                                        short tmpValue = short.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is string)
                                    {
                                        fi.SetValue(obj, node.InnerText);
                                    }
                                }
                            }
                        }
                    }
                }
                return true;
            }
            catch (Exception)
            {
                System.Windows.Forms.MessageBox.Show("读取参数失败:" + t.Name);
                return false;
            }
        }
    }
    /// <summary>
    /// xml序列化
    /// 这个是手动反射出需要用的的类型然后保存
    /// 不允许有类成员
    /// 但是可以有接口之类的存在,不会报错
    /// </summary>
    public class CXmlSaveReadMaunual
    {
        /// <summary>
        /// 传递一个对象进来,会把里面的所有公有变量保存成XML
        /// </summary>
        /// <param name="obj"></param>
        public static bool save(object obj, string xml)
        {
            Type t = obj.GetType();
            try
            {
                //文档
                System.Xml.XmlWriterSettings set = new System.Xml.XmlWriterSettings();
                set.Indent = true;
                set.NewLineOnAttributes = false;
                System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(xml, set);
                writer.WriteStartDocument();
                writer.WriteStartElement("Parameter");

                writer.WriteStartElement(t.Name);
                MemberInfo[] minfos = t.GetMembers();
                foreach (MemberInfo minfo in minfos)
                {
                    FieldInfo fi = obj.GetType().GetField(minfo.Name);
                    if (fi != null)//获取公有变量
                    {
                        writer.WriteElementString(minfo.Name, fi.GetValue(obj).ToString());
                    }
                }
                writer.WriteEndElement();

                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Flush();
                writer.Close();
                return true;
            }
            catch (Exception)
            {
                System.Windows.Forms.MessageBox.Show("保存参数失败:" + t.Name);
                return false;
            }
        }
        /// <summary>
        /// 指定XML文档,对对象中所有的公有变量赋值
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="xml"></param>
        public static bool read(object obj, string xml)
        {
            Type t = obj.GetType();
            try
            {
                //解析XML文件
                System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                doc.Load(xml);
                if (doc != null)
                {
                    System.Xml.XmlElement root = doc.DocumentElement;
                    if (root != null && root.Name == "Parameter")
                    {
                        System.Reflection.MemberInfo[] minfos = t.GetMembers();
                        foreach (System.Reflection.MemberInfo minfo in minfos)
                        {
                            System.Reflection.FieldInfo fi = obj.GetType().GetField(minfo.Name);
                            if (fi != null)
                            {
                                System.Xml.XmlNode node = root.SelectSingleNode("/Parameter/" + t.Name + "/" + minfo.Name);
                                if (node != null)
                                {
                                    if (fi.GetValue(obj) is int)
                                    {
                                        int tmpValue = int.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is float)
                                    {
                                        float tmpValue = float.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is double)
                                    {
                                        double tmpValue = double.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is bool)
                                    {
                                        bool tmpValue = bool.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is short)
                                    {
                                        short tmpValue = short.Parse(node.InnerText);
                                        fi.SetValue(obj, tmpValue);
                                    }
                                    else if (fi.GetValue(obj) is string)
                                    {
                                        fi.SetValue(obj, node.InnerText);
                                    }
                                    else if (fi.GetValue(obj) is Array)
                                    {

                                    }
                                }
                            }
                        }
                    }
                }
                return true;
            }
            catch (Exception)
            {
                System.Windows.Forms.MessageBox.Show("读取参数失败:" + t.Name);
                return false;
            }
        }
    }
}
